package exmq

import (
	"fmt"
	"github.com/spf13/viper"
	"github.com/streadway/amqp"
)

var (
	mqConn     *amqp.Connection // 链接
	mqChan     *amqp.Channel    // 链接通道
	mqHost     string           // mq地址
	mqPort     string           // mq端口
	mqUser     string           // mq用户名
	mqPassword string           // mq密码
	RabbitURL  string           // 链接参数
	err        string           // 错误
)

// 创建mq链接
/*
@return
	mqConn  rabbitmq 链接
	err 错误信息
*/
func MqConn() (mqConn *amqp.Connection, err error) {
	mqHost = viper.GetString("mq.mqHost")
	mqPort = viper.GetString("mq.mqPort")
	mqUser = viper.GetString("mq.mqUser")
	mqPassword = viper.GetString("mq.mqPassword")
	RabbitURL = fmt.Sprintf("amqp://%v:%v@%v:%v/", mqUser, mqPassword, mqHost, mqPort)
	mqConn, err = amqp.Dial(RabbitURL)
	return
}

//创建一个通道
/*
@params
	mqConn rabbitmq 链接指针
@return
	mqChan  rabbitmq 通道
	err 错误信息
*/
func MqChan(mqConn *amqp.Connection) (mqChan *amqp.Channel, err error) {
	mqChan, err = mqConn.Channel()
	return
}

//创建一个交换机
/*
@params
	mqChan rabbitmq 通道
	exchange 交换机名称
@return
	err 错误信息
*/
func Exchenge(mqChan *amqp.Channel, exchange string) (err error) {
	// 声明 exchange
	err = mqChan.ExchangeDeclare(
		exchange, //交换机名
		"direct", //类型
		false,    // is durable
		true,     // is auto-deleted
		false,    // is internal
		false,    // is noWait
		nil,      //arguments
	)
	return
}

//创建一个消息通道
/*
@params
	mqChan rabbitmq 通道
	queue 消息队列名称
@return
	err 错误信息
*/
func Queue(mqChan *amqp.Channel, queue string) (err error) {
	_, err = mqChan.QueueDeclare(
		queue, // name
		true,  // durable
		false, // delete when unused
		false, // exclusive
		false, // no-wait
		nil,   // arguments
	)
	return
}

//服务模式接收消息
/*
@params
	mqChan rabbitmq 通道
	mqRoutingKey 路由名称
	mqExchange 交换机名称
	mqQueue 消息队列名称
	consumerName 服务名称注册
@return
	msgs  接收消息的chan通道
	err 错误信息
*/
func Receive(mqChan *amqp.Channel, mqExchange string,mqQueue string, mqRoutingKey string, consumerName string) (msgs <-chan amqp.Delivery, err error) {
	Exchenge(mqChan, mqExchange)
	Queue(mqChan, mqQueue)
	mqChan.QueueBind(mqQueue, mqRoutingKey, mqExchange, false, nil)
	// 推消息模式
	msgs, err = mqChan.Consume(
		mqQueue,      // queue
		consumerName, // consumer 用于区分不同的消费者
		false,        // auto-ack 是否自动回复，【自动回复表示该条队列消息已经被处理过了，消费掉了】
		false,        // exclusive
		false,        // no-local
		false,        // no-wait
		nil,          // args
	)
	return
}
//发送rabbitmq消息
/*
@params
	mqChan rabbitmq 通道
	mqRoutingKey 路由名称
	mqExchange 交换机名称
	mqQueue 消息队列名称
	messageBody 需要发送的消息
@return
	err 错误信息
*/
func Send(mqChan *amqp.Channel, mqExchange string,mqQueue string, mqRoutingKey string, messageBody []byte) (err error) {
	Exchenge(mqChan, mqExchange)
	Queue(mqChan, mqQueue)
	mqChan.QueueBind(mqQueue, mqRoutingKey, mqExchange, false, nil)
	err = mqChan.Publish(
		mqExchange,     // exchange
		mqRoutingKey, // routing key
		false,        // mandatory
		false,        // immediate
		amqp.Publishing{
			Headers:         amqp.Table{},
			ContentType:     "text/html", // 发送的是文本
			ContentEncoding: "",
			Body:            []byte(messageBody),
		},
	)
	return
}

//关闭rabbitmq链接
func CloseConn() {
	mqConn.Close()
}
//关闭rabbitmq通道
func CloseChan() {
	mqChan.Close()
}
